<template>
    <div class="header">
        <h1>太阳系行星模拟系统</h1>
        <p class="subtitle">基于 Vue3 + Three.js + GSAP 构建的太阳系模拟，支持行星跟随视角</p>
    </div>

    <div class="canvas-container">
        <canvas id="solar-canvas"></canvas>
    </div>

    <div class="camera-info">
        <div class="camera-status" :class="{ following: isFollowing }"></div>
        <span v-if="isFollowing">正在跟随 {{ activePlanet }} · 距离: {{ distanceToPlanet }} 百万公里</span>
        <span v-else>自由视角 · 可点击行星进行跟随</span>
    </div>

    <div class="controls">
        <div class="section">
            <h2 class="section-title"><i>🌌</i> 行星选择</h2>
            <div class="planet-grid">
                <div v-for="(planet, index) in planets" :key="index" class="planet-btn"
                    :class="{ active: activePlanet === planet.name }" @click="focusPlanet(planet.name)">
                    <div class="planet-icon" :style="{ backgroundColor: planet.color }">
                        {{ planet.icon }}
                    </div>
                    <span>{{ planet.name }}</span>
                </div>
            </div>
        </div>

        <div class="section">
            <h2 class="section-title"><i>⏱️</i> 时间控制</h2>
            <div class="slider-container">
                <label>时间流速: {{ timeSpeed }}x</label>
                <input type="range" min="0" max="200" v-model="timeSpeed" @input="updateTimeSpeed">
            </div>

            <div class="btn-group">
                <button class="control-btn" @click="setTimeSpeed(1)">1x</button>
                <button class="control-btn" @click="setTimeSpeed(10)">10x</button>
                <button class="control-btn" @click="setTimeSpeed(100)">100x</button>
                <button class="control-btn" @click="pauseSimulation">暂停</button>
                <button class="control-btn" @click="resetSimulation">重置</button>
                <button class="control-btn" @click="useRealTime">实时</button>
            </div>
        </div>
    </div>

    <div class="info-panel">
        <h2 class="section-title"><i>📊</i> 行星信息</h2>
        <div v-if="activePlanet" class="planet-info">
            <div class="planet-large-icon" :style="{ backgroundColor: activePlanetData.color }">
                {{ activePlanetData.icon }}
            </div>
            <div class="planet-details">
                <h3>{{ activePlanetData.name }}</h3>
                <p>{{ activePlanetData.description }}</p>
            </div>
        </div>

        <div v-if="activePlanet" class="stats">
            <div class="stat">
                <div class="label">与太阳距离</div>
                <div class="value">{{ activePlanetData.distance }} 百万公里</div>
            </div>
            <div class="stat">
                <div class="label">公转周期</div>
                <div class="value">{{ activePlanetData.orbitPeriod }} 地球日</div>
            </div>
            <div class="stat">
                <div class="label">直径</div>
                <div class="value">{{ activePlanetData.diameter }} 公里</div>
            </div>
            <div class="stat">
                <div class="label">表面温度</div>
                <div class="value">{{ activePlanetData.temperature }}</div>
            </div>
        </div>
    </div>
</template>

<script setup>
import { computed, ref, reactive, onMounted, onUnmounted } from 'vue';
import * as THREE from 'three';
import gsap from 'gsap';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import earthJpg from '../assets/earth.jpg';

// 行星数据
const planets = ref([
    {
        name: '太阳',
        icon: '☀️',
        color: '#ffaa33',
        size: 3.0,
        orbitRadius: 0,
        speed: 0,
        description: '太阳系的中心恒星',
        distance: '0',
        orbitPeriod: '0',
        diameter: '1,392,684',
        temperature: '5,500°C'
    },
    {
        name: '水星',
        icon: '☿',
        color: '#aaaaaa',
        size: 0.4,
        orbitRadius: 8,
        speed: 4.1,
        eccentricity: 0.2056,
        perihelion: 77.456,
        inclination: 7.0,
        description: '最靠近太阳的行星',
        distance: '57.9',
        orbitPeriod: '87.969',
        diameter: '4,879',
        temperature: '167°C'
    },
    {
        name: '金星',
        icon: '♀',
        color: '#e39e1c',
        size: 0.9,
        orbitRadius: 12,
        speed: 1.6,
        eccentricity: 0.0068,
        perihelion: 131.533,
        inclination: 3.39,
        description: '地球的姐妹行星',
        distance: '108.2',
        orbitPeriod: '224.701',
        diameter: '12,104',
        temperature: '464°C'
    },
    {
        name: '地球',
        icon: '🌍',
        color: '#2277ff',
        size: 1.0,
        orbitRadius: 16,
        speed: 1,
        eccentricity: 0.0167,
        perihelion: 102.937,
        inclination: 0,
        description: '我们生活的蓝色星球',
        distance: '149.6',
        orbitPeriod: '365.256',
        diameter: '12,756',
        temperature: '15°C'
    },
    {
        name: '火星',
        icon: '♂',
        color: '#ff6633',
        size: 0.6,
        orbitRadius: 20,
        speed: 0.5,
        eccentricity: 0.0934,
        perihelion: 336.040,
        inclination: 1.85,
        description: '红色星球',
        distance: '227.9',
        orbitPeriod: '686.980',
        diameter: '6,792',
        temperature: '-65°C'
    },
    {
        name: '木星',
        icon: '♃',
        color: '#e8b384',
        size: 1.8,
        orbitRadius: 28,
        speed: 0.08,
        eccentricity: 0.0484,
        perihelion: 14.728,
        inclination: 1.31,
        description: '太阳系最大的行星',
        distance: '778.3',
        orbitPeriod: '4332.589',
        diameter: '142,984',
        temperature: '-145°C'
    },
    {
        name: '土星',
        icon: '♄',
        color: '#e3d9a7',
        size: 1.5,
        orbitRadius: 36,
        speed: 0.03,
        eccentricity: 0.0542,
        perihelion: 92.431,
        inclination: 2.49,
        description: '拥有美丽光环的气态巨行星',
        distance: '1,427',
        orbitPeriod: '10759.22',
        diameter: '120,536',
        temperature: '-178°C'
    },
    {
        name: '天王星',
        icon: '♅',
        color: '#aaf0e1',
        size: 1.1,
        orbitRadius: 42,
        speed: 0.01,
        eccentricity: 0.0472,
        perihelion: 170.964,
        inclination: 0.77,
        description: '冰巨星，自转轴倾斜',
        distance: '2,871',
        orbitPeriod: '30688.5',
        diameter: '51,118',
        temperature: '-224°C'
    },
    {
        name: '海王星',
        icon: '♆',
        color: '#5b5bff',
        size: 1.1,
        orbitRadius: 48,
        speed: 0.006,
        eccentricity: 0.0086,
        perihelion: 44.971,
        inclination: 1.77,
        description: '太阳系最远的行星',
        distance: '4,498',
        orbitPeriod: '60182',
        diameter: '49,528',
        temperature: '-218°C'
    }
]);

// 状态管理
const activePlanet = ref('太阳');
const timeSpeed = ref(1);
const simulationTime = ref(Date.now());
const isPaused = ref(false);
const realTimeMode = ref(false);
const infoHidden = ref(false);
const isFollowing = ref(false);
const distanceToPlanet = ref(0);

const J2000_EPOCH = new Date(2000, 0, 1, 12, 0, 0); // 天文标准历元

// 计算当前选中行星的数据
const activePlanetData = computed(() => {
    return planets.value.find(p => p.name === activePlanet.value) || planets.value[0];
});

// 初始化Three.js场景
let scene, camera, renderer, solarSystem, controls, realTimeUpdateCounter = 0;
let planetObjects = {};
let cameraTarget = new THREE.Vector3();
let cameraLookAt = new THREE.Vector3();

const initThreeJS = () => {
    const canvas = document.getElementById('solar-canvas');

    // 创建场景
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0x000022);
    scene.fog = new THREE.Fog(0x000033, 50, 150);

    // 创建相机
    camera = new THREE.PerspectiveCamera(
        60,
        canvas.clientWidth / canvas.clientHeight,
        0.1,
        1000
    );
    camera.position.set(0, 20, 60);
    camera.lookAt(0, 0, 0);

    controls = new OrbitControls(camera, canvas);

    // 创建渲染器
    renderer = new THREE.WebGLRenderer({
        canvas,
        antialias: true,
        alpha: true
    });
    renderer.setSize(canvas.clientWidth, canvas.clientHeight);
    renderer.setPixelRatio(window.devicePixelRatio);

    // 创建太阳系容器
    solarSystem = new THREE.Group();
    scene.add(solarSystem);

    // 添加环境光
    const ambientLight = new THREE.AmbientLight(0x333333);
    scene.add(ambientLight);

    // 添加方向光（模拟太阳光）
    const sunLight = new THREE.PointLight(0xffffff, 20000, 200);
    sunLight.position.set(0, 0, 0);
    scene.add(sunLight);

    // 创建星空背景
    createStarField();

    // 创建行星
    createPlanets();

    // 添加轨道
    createOrbits();

    // 添加光环（土星）
    createRings();

    // 开始动画
    animate();

    // 窗口大小调整
    window.addEventListener('resize', onWindowResize);
};

// 开普勒方程求解器
const solveKeplerEquation = (M, e, precision = 1e-6) => {
    let E = M; // 初始值取平近点角
    for (let i = 0; i < 50; i++) { // 最多迭代50次
        const delta = E - e * Math.sin(E) - M;
        if (Math.abs(delta) < precision) break;
        E -= delta / (1 - e * Math.cos(E));
    }

    // 计算真近点角
    const v = 2 * Math.atan2(
        Math.sqrt(1 + e) * Math.sin(E / 2),
        Math.sqrt(1 - e) * Math.cos(E / 2)
    );

    // 确保角度在0到2π之间
    return (v + 2 * Math.PI) % (2 * Math.PI);
};

// 创建星空背景
const createStarField = () => {
    const starGeometry = new THREE.BufferGeometry();
    const starMaterial = new THREE.PointsMaterial({
        color: 0xffffff,
        size: 0.15,
        transparent: true,
        sizeAttenuation: true
    });

    const starVertices = [];
    for (let i = 0; i < 8000; i++) {
        const x = (Math.random() - 0.5) * 2000;
        const y = (Math.random() - 0.5) * 2000;
        const z = (Math.random() - 0.5) * 2000;
        starVertices.push(x, y, z);
    }

    starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
    const stars = new THREE.Points(starGeometry, starMaterial);
    scene.add(stars);
};

// 创建行星
const createPlanets = () => {
    planets.value.forEach(planet => {
        if (planet.name === '太阳') {
            // 创建太阳
            const sunGeometry = new THREE.SphereGeometry(planet.size, 64, 64);
            const sunMaterial = new THREE.MeshBasicMaterial({
                color: new THREE.Color(planet.color),
                emissive: new THREE.Color(0xffaa33),
                emissiveIntensity: 1.0
            });
            const sun = new THREE.Mesh(sunGeometry, sunMaterial);
            solarSystem.add(sun);
            planetObjects[planet.name] = sun;

            // 添加太阳光晕
            const sunGlowGeometry = new THREE.SphereGeometry(planet.size * 1.2, 32, 32);
            const sunGlowMaterial = new THREE.MeshBasicMaterial({
                color: new THREE.Color(0xffaa33),
                transparent: true,
                opacity: 0.3
            });
            const sunGlow = new THREE.Mesh(sunGlowGeometry, sunGlowMaterial);
            solarSystem.add(sunGlow);
        } else {
            // 创建行星轨道容器
            const orbitContainer = new THREE.Group();
            solarSystem.add(orbitContainer);

            // 创建行星
            const planetGeometry = new THREE.SphereGeometry(planet.size, 48, 48);
            const planetMaterial = new THREE.MeshStandardMaterial({
                color: new THREE.Color(planet.color),
                map: planet.name == '地球' ? new THREE.TextureLoader().load(earthJpg) : null
            });
            const planetMesh = new THREE.Mesh(planetGeometry, planetMaterial);

            // 设置行星位置
            planetMesh.position.x = planet.orbitRadius;
            orbitContainer.add(planetMesh);

            // 设置初始旋转角度
            orbitContainer.rotation.y = Math.random() * Math.PI * 2;

            // 保存行星引用
            planetObjects[planet.name] = orbitContainer;
        }
    });
};

// 创建土星光环
const createRings = () => {
    const ringGeometry = new THREE.RingGeometry(1.8, 3.0, 64);
    const ringMaterial = new THREE.MeshBasicMaterial({
        color: 0xf1e5c2,
        side: THREE.DoubleSide,
        transparent: true,
        opacity: 0.7
    });
    const ring = new THREE.Mesh(ringGeometry, ringMaterial);
    ring.rotation.x = Math.PI / 3;
    ring.rotation.z = Math.PI / 4;

    // 找到土星并添加光环
    const saturn = planetObjects['土星'];
    if (saturn) {
        const planet = saturn.children[0];
        ring.position.x = planet.position.x;
        ring.position.y = planet.position.y;
        ring.position.z = planet.position.z;
        saturn.add(ring);
    }
};

// 创建行星轨道
const createOrbits = () => {
    planets.value.forEach(planet => {
        if (planet.orbitRadius > 0) {
            const orbitGeometry = new THREE.BufferGeometry();
            const orbitMaterial = new THREE.LineBasicMaterial({
                color: new THREE.Color(0x3366aa),
                transparent: true,
                opacity: 0.3
            });

            const points = [];
            for (let i = 0; i <= 128; i++) {
                const angle = (i / 128) * Math.PI * 2;
                points.push(
                    Math.cos(angle) * planet.orbitRadius,
                    0,
                    Math.sin(angle) * planet.orbitRadius
                );
            }

            orbitGeometry.setAttribute('position', new THREE.Float32BufferAttribute(points, 3));
            const orbit = new THREE.Line(orbitGeometry, orbitMaterial);
            solarSystem.add(orbit);
        }
    });
};

// 根据真实时间计算行星位置
const useRealTime = () => {
    realTimeMode.value = true;
    timeSpeed.value = 1;
    isPaused.value = false;
    updateRealTimePositions();
};

const updateRealTimePositions = () => {
    const now = new Date();
    const daysSinceJ2000 = (now - J2000_EPOCH) / (1000 * 60 * 60 * 24);

    planets.value.forEach(planet => {
        if (planet.name !== '太阳') {
            const orbitContainer = planetObjects[planet.name];
            if (orbitContainer) {
                // 计算平近点角
                const meanAnomaly = (2 * Math.PI * daysSinceJ2000) / planet.orbitPeriod;

                // 求解开普勒方程得到真近点角
                const trueAnomaly = solveKeplerEquation(
                    meanAnomaly,
                    planet.eccentricity
                );

                // 应用近日点经度修正（转换为弧度）
                const perihelionRad = THREE.MathUtils.degToRad(planet.perihelion);
                orbitContainer.rotation.y = trueAnomaly + perihelionRad;
            }
        }
    });
};

// 动画循环
const animate = () => {
    requestAnimationFrame(animate);

    if (!isPaused.value) {
        // 更新时间
        const now = Date.now();
        const delta = (now - simulationTime.value) * 0.001 * timeSpeed.value;
        simulationTime.value = now;

        controls.update();

        if (realTimeMode.value) {
            // 实时模式：每秒更新一次位置（平衡精度和性能）
            realTimeUpdateCounter += delta;
            if (realTimeUpdateCounter >= 1.0) {
                updateRealTimePositions();
                realTimeUpdateCounter = 0;
            }
        } else {
            // 更新行星位置
            planets.value.forEach(planet => {
                if (planet.name !== '太阳') {
                    const orbitContainer = planetObjects[planet.name];
                    if (orbitContainer) {
                        orbitContainer.rotation.y += delta * planet.speed * 0.01;
                    }
                }
            });

        }
        // 更新相机跟随
        if (isFollowing.value) {
            updateCameraFollow();
        }

    }

    renderer.render(scene, camera);
};

// 更新相机跟随
const updateCameraFollow = () => {
    const planet = planets.value.find(p => p.name === activePlanet.value);
    if (!planet || planet.name === '太阳') return;

    const orbitContainer = planetObjects[planet.name];
    if (!orbitContainer) return;

    // 计算行星位置（世界坐标）
    const planetPosition = new THREE.Vector3();
    orbitContainer.children[0].getWorldPosition(planetPosition);

    // 计算相机位置（在行星后方和上方）
    const cameraOffset = new THREE.Vector3(
        -planet.size * 6,
        planet.size * 3,
        0
    );

    // 应用行星旋转
    cameraOffset.applyQuaternion(orbitContainer.quaternion);

    // 计算目标位置
    cameraTarget.copy(planetPosition).add(cameraOffset);

    // 平滑移动相机
    camera.position.lerp(cameraTarget, 0.05);

    // 相机始终看向行星
    cameraLookAt.lerp(planetPosition, 0.05);
    camera.lookAt(cameraLookAt);

    // 更新距离显示
    distanceToPlanet.value = Math.round(camera.position.distanceTo(planetPosition) / 2);
};

// 窗口大小调整
const onWindowResize = () => {
    const canvas = document.getElementById('solar-canvas');
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(canvas.clientWidth, canvas.clientHeight);
};

// 聚焦行星
const focusPlanet = (planetName) => {
    activePlanet.value = planetName;
    isFollowing.value = true;

    const planet = planets.value.find(p => p.name === planetName);
    if (!planet) return;

    // 如果是太阳，特殊处理
    if (planetName === '太阳') {
        gsap.to(camera.position, {
            x: 0,
            y: 20,
            z: 40,
            duration: 2,
            ease: "power2.inOut",
            onUpdate: () => {
                camera.lookAt(0, 0, 0);
            },
            onComplete: () => {
                isFollowing.value = false;
            }
        });
    } else {
        // 设置相机跟随
        updateCameraFollow();
    }
};

// 更新时间速度
const updateTimeSpeed = () => {
    if (timeSpeed.value < 1) timeSpeed.value = 1;
};

// 设置时间速度
const setTimeSpeed = (speed) => {
    realTimeMode.value = false;
    timeSpeed.value = speed;
};

// 暂停模拟
const pauseSimulation = () => {
    realTimeMode.value = false;
    isPaused.value = !isPaused.value;
};

// 重置模拟
const resetSimulation = () => {
    realTimeMode.value = false;
    simulationTime.value = Date.now();
    timeSpeed.value = 1;
    isPaused.value = false;
    isFollowing.value = false;

    // 重置行星位置
    planets.value.forEach(planet => {
        if (planet.name !== '太阳') {
            const orbitContainer = planetObjects[planet.name];
            if (orbitContainer) {
                orbitContainer.rotation.y = Math.random() * Math.PI * 2;
            }
        }
    });

    // 重置相机
    gsap.to(camera.position, {
        x: 0,
        y: 20,
        z: 60,
        duration: 1.5,
        ease: "power2.inOut",
        onUpdate: () => {
            camera.lookAt(0, 0, 0);
        }
    });

    activePlanet.value = '太阳';
};

// 切换信息面板
const toggleInfoPanel = () => {
    infoHidden.value = !infoHidden.value;
};

// 初始化
onMounted(() => {
    initThreeJS();
    useRealTime();
    // 初始聚焦地球
    setTimeout(() => focusPlanet('地球'), 1500);
});
</script>
